﻿/*
 * Created by SharpDevelop.
 * User: XiaoSanYa
 * Date: 2016/10/30
 * Time: 17:36
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Xml;

namespace AutoRunner.Device
{
	public enum ACTION_TYPE
	{
		RUN = 0,
		MOVE,
		CARRY
	}
	
	/// <summary>
	/// 自动流水线上的一个物理位置，如上机位，测试位
	/// </summary>
	public struct Point
	{
		//名称和描述
		public string Name;		
		public string Desc;
		//正常与否控制位
		public bool TobeOK;	
		//容量		
		public int Capacity;
		//存量			
		public int Stock;
		
		public Point(string name, int capacity = 1, int stock = 0)
		{
			Name = name;
			Desc = "";
			TobeOK = true;
			Capacity = capacity;
			Stock = stock;
		}
		
		//是否可用
		public bool IsReady()
		{
			if(TobeOK)
			{
				if((Capacity - Stock)> 0)
					return true;
				else
					return false;
			}
			else
				return false;
		}
	}
	
	/// <summary>
	/// PLC的M、D软元寄存器
	/// </summary>
	public struct MDReg
	{
		public string Name;
		public int Value;
		
		public MDReg(string name, int value)
		{
			Name = name;
			Value = value;
		}
	}
	
	/// <summary>
	/// 执行机构
	/// </summary>
	public struct Actuator
	{
		public string Name;
		public string Desc;
		public bool TobeOK;
		public bool IsRunning;
		
		public Actuator(string name, string desc = "")
		{
			Name = name;
			Desc = desc;
			TobeOK = true;
			IsRunning = false;
		}
		
		public bool IsReady()
		{
			if(TobeOK)
			{
				if(IsRunning)
					return false;
				else
					return true;
			}
			else
				return false;
		}
	}
	
	
	/// <summary>
	/// 从一个点到另一个点的动作，如上机
	/// </summary>
	public class Action
	{
		public string Name;		
		public string Desc;
		public string ActorName;
		public ACTION_TYPE Type;
		public string RequireCode;	
		public string RunCode;
		public string DoneCode;
		public string SrcPoint;
		public string DstPoint;
		public long Timecost;		
		public long Starttime;
		public bool AutoRun;
		public bool ToRun;
		
		public Action(string name)
		{
			Name = name;
			Desc = "";
			ToRun = false;
		}

	}
	
	/// <summary>
	/// PLC
	/// </summary>
	public class PLCDevice
	{
		public string Name;
		public string Desc;
		public bool TobeOK;
		public bool ToRun;
		
		private Hashtable Points;
		private Hashtable Actuators;
		private Hashtable MDRegs;
		private Hashtable Actions;
		
		string IP;
		int Port;
		
		public PLCDevice()
		{
			TobeOK = true;
			ToRun = false;
			
			Points = new Hashtable();
			Actuators = new Hashtable();
			MDRegs = new Hashtable();
			Actions = new Hashtable();
			
		}
		
		/// <summary>
		/// 从文件获取配置，初始化各个集
		/// </summary>
		/// <param name="filepath"></param>
		/// <returns></returns>
		public bool ConfigFromFile(string filepath)
		{
			XmlDocument xmlDoc=new XmlDocument(); 
			xmlDoc.Load(filepath); 
			XmlNode pntNode = xmlDoc.SelectSingleNode("/PLC/Points");
			XmlNode atrNode = xmlDoc.SelectSingleNode("/PLC/Actuators");
			XmlNode mdrNode = xmlDoc.SelectSingleNode("/PLC/MDRegs");
			XmlNode actNode = xmlDoc.SelectSingleNode("/PLC/Actions");
			
			try{				
				foreach(XmlNode xn in pntNode.ChildNodes)
				{
					XmlElement xe = (XmlElement)xn;					
					string name = xe.GetAttribute("Name");
					int capacity = int.Parse(xe.GetAttribute("Capacity"));
					int stock = int.Parse(xe.GetAttribute("Stock"));
					Points.Add(name, new Point(name, capacity, stock));						
				}
				
				foreach(XmlNode xn in atrNode.ChildNodes)
				{
					XmlElement xe = (XmlElement)xn;					
					string name = xe.GetAttribute("Name");
					Actuators.Add(name, new Actuator(name));					
				}
				
				foreach(XmlNode xn in mdrNode.ChildNodes)
				{
					XmlElement xe = (XmlElement)xn;					
					string name = xe.GetAttribute("Name");
					int value = int.Parse(xe.GetAttribute("Value"));
					MDRegs.Add(name, new MDReg(name, value));					
				}
				
				foreach(XmlNode xn in actNode.ChildNodes)
				{
					XmlElement xe = (XmlElement)xn;					
					string name = xe.GetAttribute("Name");
					Action act = new Action(name);
					
					string type = xe.GetAttribute("Type");
					if(type == "CARRY")
						act.Type = ACTION_TYPE.CARRY;
					else if(type == "MOVE")
						act.Type = ACTION_TYPE.MOVE;
					else
						act.Type = ACTION_TYPE.RUN;
					
					act.RequireCode = xe.GetAttribute("RequireCode");
					act.RunCode = xe.GetAttribute("RunCode");
					act.DoneCode = xe.GetAttribute("DoneCode");
					act.SrcPoint = xe.GetAttribute("SrcPoint");
					act.DstPoint = xe.GetAttribute("DstPoint");
					act.ActorName = xe.GetAttribute("ActorName");
					act.AutoRun = (xe.GetAttribute("AutoRun") == "0") ? false : true;
					act.Timecost = int.Parse(xe.GetAttribute("TimeCost"));
					
					Points.Add(name, act);
				}
			}
			catch{
				return false;
			}
			return true;
		}
		
		
		/// <summary>
		/// 设置PLC的IP和Port
		/// </summary>
		/// <param name="ip"></param>
		/// <param name="port"></param>
		public void SetAddress(string ip, int port)
		{
			IP = ip;
			Port = port;
		}
		
		/// <summary>
		/// 启动
		/// </summary>
		public void Start()
		{
			ToRun = true;
			
			//启动通讯线程
			StartServer(IP, Port);
		}
		
		/// <summary>
		/// 启动PLC Server
		/// </summary>
		private void StartServer(string ip, int port)
		{
			PLCComm comm = new PLCComm();
			comm.StartServer(ip, port);
		}
		
	
		/// <summary>
		/// 停止
		/// </summary>
		public void Stop()
		{
			ToRun = false;
		}
		
		/// <summary>
		/// 动作循环处理
		/// </summary>
		private void ActionLoop()
		{
			
		}
		
		/// <summary>
		/// 动作等待执行
		/// </summary>
		/// <param name="act"></param>
		private void ActionWait(Action act)
		{
			
		}
		
		/// <summary>
		/// 动作执行
		/// </summary>
		/// <param name="act"></param>
		private void ActionRun(Action act)
		{
			
		}
		
		
	}
}